<template>
  <div :id="tableName + '_form'">
    <div
      v-if="!!dbData.id && !!onlineExtConfigJson.reportPrintShow"
      style="text-align: right; position: absolute; top: 6px; right: 20px; z-index: 999"
    >
      <PrinterOutlined title="打印" click="onOpenReportPrint" style="font-size: 16px" />
    </div>
    <BasicForm ref="onlineFormRef" @register="registerForm" />
    <a-tabs v-if="hasSubTable" v-model:activeKey="subActiveKey">
      <a-tab-pane :tab="sub.describe" :forceRender="true" :key="index + ''" v-for="(sub, index) in subTabInfo">
        <div v-if="sub.relationType == 1" :style="{ 'overflow-y': 'auto', 'overflow-x': 'hidden', 'max-height': subFormHeight + 'px' }">
          <online-sub-form
            :ref_for="true"
            :ref="refMap[sub.key]"
            :table="sub.key"
            :disabled="onlineFormDisabled"
            :form-template="formTemplate"
            :main-id="getSubTableForeignKeyValue(sub.foreignKey)"
            :properties="sub.properties"
            :required-fields="sub.requiredFields"
            :is-update="isUpdate"
            @formChange="(arg) => handleSubFormChange(arg, sub.key)"
          />
        </div>
        <div v-else>
          <JVxeTable
            :ref_for="true"
            :ref="refMap[sub.key]"
            toolbar
            keep-source
            row-number
            row-selection
            :height="subTableHeight"
            :disabled="onlineFormDisabled"
            :columns="sub.columns"
            :dataSource="subDataSource[sub.key]"
            @valueChange="(event) => handleValueChange(event, sub.key)"
            @authPre="getSubTableAuthPre(sub.key)"
            @added="($event) => handleAdded(sub, $event)"
            @executeFillRule="($event) => handleSubTableDefaultValue(sub, $event)"
          >
            <template #toolbarSuffix>
              <a-button type="primary" @click="openSubFormModalForAdd(sub)"><diff-outlined /></a-button>
              <a-button type="primary" @click="openSubFormModalForEdit(sub)"><form-outlined /></a-button>
            </template>
          </JVxeTable>
        </div>
      </a-tab-pane>
    </a-tabs>
    <Loading :loading="loading" :absolute="false" />
    <slot name="bottom"></slot>
    <online-pop-modal :request="popModalRequest" :id="popTableName" @register="registerPopModal" @success="getPopFormData" topTip isVxeTableData />
  </div>
</template>
<script lang="ts">
  import { useMessage } from '/@/hooks/web/useMessage';
  import { ref, reactive, computed, unref, nextTick, toRaw, defineComponent } from 'vue';
  import { BasicForm, useForm } from '/@/components/Form/index';
  import { VALIDATE_FAILED, SUBMIT_FLOW_KEY, SUBMIT_FLOW_ID, ONL_FORM_TABLE_NAME } from '../../use/FormSchemaFactory';
  import { defHttp } from '/@/utils/http/axios';
  import { sleep, goJmReportViewPage } from '/@/utils';
  import { useOnlineFormContext, useFormItems, useEnhance, loadFormFieldsDefVal, getRefPromise } from '../../use/useAutoForm';
  import OnlineSubForm from './OnlineSubForm.vue';
  import OnlinePopModal from './OnlinePopModal.vue';
  import { Loading } from '/@/components/Loading';
  import '/@/components/jeecg/JVxeTable/types';
  import { getToken } from '/@/utils/auth';
  import { PrinterOutlined, DiffOutlined, FormOutlined } from '@ant-design/icons-vue';
  import '/@/hooks/core/useContext';
  import '/@/utils/mitt';
  import { useModal } from '/@/components/Modal';
  import { pick, omit } from 'lodash-es';

  const urlObject = {
    optPre: '/api-online/online/cgform/api/form/',
    urlButtonAction: '/api-online/online/cgform/api/doButton',
  };

  export default defineComponent({
    name: 'OnlineForm',
    components: {
      BasicForm,
      Loading,
      OnlineSubForm,
      PrinterOutlined,
      DiffOutlined,
      FormOutlined,
      OnlinePopModal,
    },
    props: {
      id: {
        type: String,
        default: '',
      },
      formTemplate: {
        type: Number,
        default: 1,
      },
      disabled: {
        type: Boolean,
        default: false,
      },
      isTree: {
        type: Boolean,
        default: false,
      },
      pidField: {
        type: String,
        default: '',
      },
      submitTip: {
        type: Boolean,
        default: true,
      },
    },
    emits: ['success', 'rendered'],
    setup(props, { emit }) {
      console.log('onlineForm-setup》》');
      const { createMessage: $message } = useMessage();
      const onlineFormRef = ref(null);
      const single = ref(true);
      const loading = ref(false);
      const tableType = ref(1);
      const customEditSubmitUrl = ref('');
      const submitFlowFlag = ref(false);
      const isUpdate = ref(false);
      const onlineExtConfigJson = reactive({
        reportPrintShow: 0,
        reportPrintUrl: '',
        joinQuery: 0,
        modelFullscreen: 0,
        modalMinWidth: '',
        commentStatus: 0,
      });
      const { onlineFormContext, resetContext } = useOnlineFormContext();
      const {
        formSchemas,
        defaultValueFields,
        changeDataIfArray2String,
        tableName,
        dbData,
        checkOnlyFieldValue,
        hasSubTable,
        subTabInfo,
        refMap,
        subDataSource,
        baseColProps,
        createFormSchemas,
        linkDownList,
        fieldDisplayStatus,
      } = useFormItems(props, onlineFormRef);
      let { EnhanceJS, initCgEnhanceJs } = useEnhance(onlineFormContext, false);
      const [registerForm, { setProps, validate, resetFields, setFieldsValue, updateSchema, getFieldsValue, scrollToField }] = useForm({
        schemas: formSchemas,
        showActionButtonGroup: false,
        baseColProps,
      });
      const onlineFormDisabled = ref(false);
      function handleFormDisabled() {
        let flag = props.disabled;
        onlineFormDisabled.value = flag;
        setProps({ disabled: flag });
      }
      async function show(status, record, param) {
        console.log('OnlineForm新增编辑进入表单》》form', record);
        await updatePidFieldDict();
        customEditSubmitUrl.value = '';
        await resetFields();
        dbData.value = '';
        let flag = unref(status);
        isUpdate.value = flag;
        if (flag) {
          await edit(record);
        } else {
          editSubVxeTableData();
        }
        nextTick(() => {
          if (!flag && param) {
            setFieldsValue(param);
          }
          handleDefaultValue();
          handleCgButtonClick('js', 'loaded');
          handleFormDisabled();
        });
      }
      async function updatePidFieldDict() {
        if (props.isTree === true) {
          let pidFieldName = props.pidField;
          let arr = formSchemas.value;
          if (arr && arr.length > 0) {
            let temp = arr.filter((item) => item.field === pidFieldName);
            if (temp.length > 0) {
              await updateSchema({
                field: pidFieldName,
                componentProps: {
                  reload: new Date().getTime(),
                },
              });
            }
          } else {
            console.log('没有拿到表单配置信息，可能是第一次打开新增页面');
          }
        }
      }
      function handleDefaultValue() {
        if (unref(isUpdate) === false) {
          let fieldProperties = toRaw(defaultValueFields[tableName.value]);
          loadFormFieldsDefVal(fieldProperties, (values) => {
            setFieldsValue(values);
          });
        }
      }
      function handleSubTableDefaultValue(sub, $event) {
        let subFieldProperties = toRaw(defaultValueFields[sub.key]);
        loadFormFieldsDefVal(subFieldProperties, (values) => {
          const { row, target } = $event;
          let v = [{ rowKey: row.id, values: Object.assign({}, values) }];
          target.setValues(v);
        });
      }
      async function edit(record) {
        let formData = await getFormData(record.id);
        dbData.value = Object.assign({}, record, formData);
        let arr = realFormFieldNames.value;
        let values = pick(formData, ...arr);
        if (props.disabled) {
          Object.keys(values).map((k) => {
            if (!values[k] && values[k] !== 0 && values[k] !== '0') {
              delete values[k];
            }
          });
        }
        await setFieldsValue(values);
        editSubVxeTableData(formData);
      }
      function editSubVxeTableData(record) {
        if (!record) {
          record = {};
        }
        let keys = Object.keys(subDataSource.value);
        if (keys && keys.length > 0) {
          let obj = {};
          for (let key of keys) {
            obj[key] = record[key] || [];
          }
          subDataSource.value = obj;
        }
      }
      let realFormFieldNames = computed(() => {
        let arr = formSchemas.value;
        let names = [];
        for (let a of arr) {
          names.push(a.field);
        }
        return names;
      });
      function getFormData(dataId) {
        let url = `${urlObject.optPre}${props.id}/${dataId}`;
        return new Promise((resolve, reject) => {
          defHttp
            .get({ url }, { isTransformResponse: false })
            .then((res) => {
              if (res.success) {
                resolve(res.data);
              } else {
                reject();
                $message.warning(res.msg);
              }
            })
            .catch(() => {
              reject();
            });
        });
      }
      async function createRootProperties(data) {
        tableType.value = data.head.tableType;
        tableName.value = data.head.tableName;
        single.value = data.head.tableType == 1;
        handleExtConfigJson(data.head.extConfigJson);
        createFormSchemas(data.schema.properties, data.schema.required, checkOnlyFieldValue);
        EnhanceJS = initCgEnhanceJs(data.enhanceJs);
        emit('rendered', onlineExtConfigJson);
        let formRefObject = await getRefPromise(onlineFormRef);
        formRefObject.$formValueChange = (field, value, changeFormData) => {
          onValuesChange(field, value);
          if (changeFormData) {
            setFieldsValue(changeFormData);
          }
        };
      }
      function handleExtConfigJson(jsonStr) {
        let extConfigJson = { reportPrintShow: 0, reportPrintUrl: '', joinQuery: 0, modelFullscreen: 1, modalMinWidth: '', commentStatus: 0 };
        if (jsonStr) {
          extConfigJson = JSON.parse(jsonStr);
        }
        Object.keys(extConfigJson).map((k) => {
          onlineExtConfigJson[k] = extConfigJson[k];
        });
      }
      function handleSubmit() {
        if (single.value === true) {
          handleSingleSubmit();
        } else {
          handleOne2ManySubmit();
        }
      }
      function handleOne2ManySubmit() {
        validateAll().then((formData) => {
          handleApplyRequest(formData);
        });
      }
      function validateAll() {
        let temp = {};
        return new Promise((resolve, reject) => {
          validate().then(
            (values) => resolve(values),
            ({ errorFields }) => {
              if (errorFields && errorFields.length > 0) {
                scrollToField(errorFields[0][0]);
              }
              reject(VALIDATE_FAILED);
            }
          );
        })
          .then((result) => {
            Object.assign(temp, changeDataIfArray2String(result));
            return validateSubTableFields();
          })
          .then((allTableData) => {
            Object.assign(temp, allTableData);
            return Promise.resolve(temp);
          })
          .catch((e) => {
            if (e === VALIDATE_FAILED || (e == null ? void 0 : e.code) === VALIDATE_FAILED) {
              $message.warning('校验未通过');
              if (e.key) {
                changeTab(e.key);
              }
            } else {
              console.error(e);
            }
            return Promise.reject(null);
          });
      }
      function changeTab(key) {
        let arr = subTabInfo.value;
        for (let i = 0; i < arr.length; i++) {
          if (key == arr[i].key) {
            let activeKey = i + '';
            if (subActiveKey.value === activeKey) {
              break;
            }
            subActiveKey.value = activeKey;
            if (arr[i].relationType === 0) {
              let instance = getSubTableInstance(key);
              sleep(300, () => (instance == null ? void 0 : instance.validateTable()));
            }
            break;
          }
        }
      }
      function validateSubTableFields() {
        return new Promise(async (resolve, reject) => {
          let subData = {};
          try {
            let arr = subTabInfo.value;
            for (let i = 0; i < arr.length; i++) {
              let key = arr[i].key;
              let instance = getSubTableInstance(key);
              if (arr[i].relationType == 1) {
                try {
                  let subFormData = await instance.getAll();
                  subData[key] = [];
                  subData[key].push(subFormData);
                } catch (e) {
                  throw { code: VALIDATE_FAILED, key };
                }
              } else {
                let errMap = await instance.fullValidateTable();
                if (errMap) {
                  throw { code: VALIDATE_FAILED, key };
                }
                subData[key] = instance.getTableData();
              }
            }
          } catch (e) {
            reject(e);
          }
          resolve(subData);
        });
      }
      async function handleSingleSubmit() {
        try {
          let values = await validate();
          values = Object.assign({}, dbData.value, values);
          values = changeDataIfArray2String(values);
          loading.value = true;
          handleApplyRequest(values);
        } finally {
          loading.value = false;
        }
      }
      function handleApplyRequest(formData) {
        customBeforeSubmit(context, formData)
          .then(() => {
            doApplyRequest(formData);
          })
          .catch((msg) => {
            $message.warning(msg);
          });
      }
      function doApplyRequest(formData) {
        Object.keys(formData).map((key) => {
          if (Array.isArray(formData[key])) {
            if (formData[key].length == 0) {
              formData[key] = '';
            }
          }
        });
        console.log('提交表单数据》》》form:', formData);
        let customUrl = customEditSubmitUrl.value;
        let url = `${urlObject.optPre}${props.id}?tabletype=${tableType.value}`;
        if (customUrl) {
          url = `${customUrl}?tabletype=${tableType.value}`;
        }
        if (submitFlowFlag.value === true) {
          formData[SUBMIT_FLOW_KEY] = 1;
        }
        let method = isUpdate.value === true ? 'put' : 'post';
        defHttp
          .request({ url, method, params: formData }, { isTransformResponse: false })
          .then((res) => {
            if (res.success) {
              if (res.data) {
                formData[SUBMIT_FLOW_ID] = res.data;
              }
              emit('success', formData);
              if (props.submitTip === true) {
                $message.success(res.msg);
              }
            } else {
              $message.warning(res.msg);
            }
          })
          .finally(() => {
            loading.value = false;
          });
      }
      function triggleChangeValues(values, id, target) {
        if (id && target) {
          if (target.vxeProps) {
            target.setValues([
              {
                rowKey: id,
                values,
              },
            ]);
          } else {
            target.setValues(values);
          }
        } else {
          setFieldsValue(values);
        }
      }
      function triggleChangeValue(field, value) {
        let obj = {};
        obj[field] = value;
        setFieldsValue(obj);
      }
      const subActiveKey = ref('0');
      const subFormHeight = ref(300);
      const subTableHeight = ref(340);
      function getSubTableForeignKeyValue(key) {
        if (isUpdate.value === true) {
          let formData = dbData.value;
          return getValueIgnoreCase(formData, key);
        }
        return '';
      }
      function getValueIgnoreCase(data, key) {
        if (data) {
          let temp = data[key];
          if (!temp && temp !== 0) {
            temp = data[key.toLowerCase()];
            if (!temp && temp !== 0) {
              temp = data[key.toUpperCase()];
            }
          }
          return temp;
        }
        return '';
      }
      function handleSubFormChange(valueObj, tableKey) {
        if (EnhanceJS && EnhanceJS[tableKey + '_onlChange']) {
          let tableChangeObj = EnhanceJS[tableKey + '_onlChange']();
          let columnKey = Object.keys(valueObj)[0];
          if (tableChangeObj[columnKey]) {
            let subRef = getSubTableInstance(tableKey);
            let formEvent = subRef.getFormEvent();
            let event = Object.assign(
              {
                column: { key: columnKey },
                value: valueObj[columnKey],
              },
              formEvent
            );
            tableChangeObj[columnKey].call(onlineFormContext, onlineFormContext, event);
          }
        }
      }
      function handleValueChange(event, tableKey) {
        if (EnhanceJS && EnhanceJS[tableKey + '_onlChange']) {
          let tableChangeObj = EnhanceJS[tableKey + '_onlChange'](onlineFormContext);
          if (event.column === 'all') {
            let keys = Object.keys(tableChangeObj);
            if (keys.length > 0) {
              for (let key of keys) {
                tableChangeObj[key].call(onlineFormContext, onlineFormContext, event);
              }
            }
          } else {
            let columnKey = event.column.key || event.col.key;
            if (tableChangeObj[columnKey]) {
              if (event.row && event.row.id) {
                tableChangeObj[columnKey].call(onlineFormContext, onlineFormContext, event);
              }
            }
          }
        }
      }
      function handleAdded(sub, event) {
        console.log('handleAdded', sub, event);
        handleSubTableDefaultValue(sub, event);
      }
      function getSubTableAuthPre(table) {
        return 'online_' + table + ':';
      }
      async function onValuesChange(columnKey, value) {
        if (!EnhanceJS || !EnhanceJS['onlChange']) {
          return false;
        }
        if (!columnKey) {
          return false;
        }
        let tableChangeObj = EnhanceJS['onlChange']();
        if (tableChangeObj[columnKey]) {
          let formData = await getFieldsValue();
          let event = {
            row: formData,
            column: { key: columnKey },
            value,
          };
          tableChangeObj[columnKey].call(onlineFormContext, onlineFormContext, event);
        }
      }
      function handleCgButtonClick(optType, buttonCode) {
        if ('js' == optType) {
          if (EnhanceJS && EnhanceJS[buttonCode]) {
            EnhanceJS[buttonCode].call(onlineFormContext, onlineFormContext);
          }
        } else if ('action' == optType) {
          let formData = dbData.value;
          let params = {
            formId: props.id,
            buttonCode,
            dataId: formData.id,
            uiFormData: Object.assign({}, formData),
          };
          defHttp
            .post(
              {
                url: `${urlObject.urlButtonAction}`,
                params,
              },
              { isTransformResponse: false }
            )
            .then((res) => {
              if (res.success) {
                $message.success('处理完成!');
              } else {
                $message.warning('处理失败!');
              }
            });
        }
      }
      function clearSubRows(tbname) {
        let instance = getSubTableInstance(tbname);
        let rows = [...instance.getNewDataWithId(), ...subDataSource.value[tbname]];
        if (!rows || rows.length == 0) {
          return false;
        }
        let ids = [];
        for (let i of rows) {
          ids.push(i.id);
        }
        instance.removeRowsById(ids);
      }
      function addSubRows(tbname, rows) {
        if (!rows) {
          return false;
        }
        let instance = getSubTableInstance(tbname);
        if (typeof rows == 'object') {
          instance.addRows(rows, true);
        } else {
          $message.error('添加子表数据,参数不识别!');
        }
      }
      function clearThenAddRows(tbname, rows) {
        clearSubRows(tbname);
        addSubRows(tbname, rows);
      }
      function changeOptions(field, options) {
        if (!options && options.length <= 0) {
          options = [];
        }
        options.map((item) => {
          if (!item.hasOwnProperty('label')) {
            item['label'] = item.text;
          }
        });
        updateSchema({
          field,
          componentProps: {
            options,
          },
        });
      }
      function customBeforeSubmit(that, formData) {
        if (EnhanceJS && EnhanceJS['beforeSubmit']) {
          return EnhanceJS['beforeSubmit'](that, formData);
        } else {
          return Promise.resolve();
        }
      }
      function handleCustomFormSh(show2, hide) {
        let plain = toRaw(fieldDisplayStatus);
        if (show2 && show2.length > 0) {
          Object.keys(plain).map((k) => {
            if (!k.endsWith('_load') && show2.indexOf(k) < 0) {
              fieldDisplayStatus[k] = false;
            }
          });
        } else if (hide && hide.length > 0) {
          Object.keys(plain).map((k) => {
            if (hide.indexOf(k) >= 0) {
              fieldDisplayStatus[k] = false;
            }
          });
        }
      }
      async function handleCustomFormEdit(record, editSubmitUrl) {
        console.log('自定义弹窗打开online表单》》form', record);
        customEditSubmitUrl.value = editSubmitUrl;
        await resetFields();
        dbData.value = '';
        isUpdate.value = true;
        await edit(record);
        nextTick(() => {
          handleCgButtonClick('js', 'loaded');
        });
      }
      function getSubTableInstance(tableName2) {
        let instance = refMap[tableName2].value;
        if (instance instanceof Array) {
          instance = instance[0];
        }
        if (!instance) {
          $message.warning('子表ref找不到:' + tableName2);
          return;
        }
        return instance;
      }
      function onOpenReportPrint() {
        let url = onlineExtConfigJson.reportPrintUrl;
        let id = dbData.value.id;
        let token = getToken();
        goJmReportViewPage(url, id, token);
      }
      const [registerPopModal, { openModal: openPopModal }] = useModal();
      const popTableName = ref('');
      const popModalRequest = ref(true);
      function openSubFormModalForAdd(sub) {
        popTableName.value = sub.id;
        popModalRequest.value = false;
        openPopModal(true, { isUpdate: false });
      }
      function openSubFormModalForEdit(sub) {
        let ref2 = getSubTableInstance(sub.key);
        let arr = ref2.getSelectedData();
        if (arr.length != 1) {
          $message.warning('请选择一条数据');
          return;
        }
        popTableName.value = sub.id;
        popModalRequest.value = false;
        openPopModal(true, { isUpdate: true, record: arr[0] });
      }
      function getPopFormData(data) {
        const tableName2 = data[ONL_FORM_TABLE_NAME];
        let record = omit(data, [ONL_FORM_TABLE_NAME]);
        if (record.id) {
          let values = omit(Object.assign({}, record), 'id');
          let arr = [{ rowKey: record.id, values }];
          let instance = getSubTableInstance(tableName2);
          instance.setValues(arr);
        } else {
          let instance = getSubTableInstance(tableName2);
          instance.addRows(record, { isOnlineJS: false, setActive: false, emitChange: true });
        }
      }
      function onCloseModal() {
        let arr = subTabInfo.value;
        if (arr && arr.length > 0) {
          for (let item of arr) {
            if (item.relationType == 1);
            else {
              let inst = getSubTableInstance(item.key);
              if (inst) {
                inst.clearSelection();
              }
            }
          }
        }
      }
      function executeMainFillRule() {
        let formData = getFieldsValue();
        let fieldProperties = toRaw(defaultValueFields[tableName.value]);
        loadFormFieldsDefVal(
          fieldProperties,
          (values) => {
            setFieldsValue(values);
          },
          formData
        );
      }
      function executeSubFillRule(subKey, $event) {
        let subList = subTabInfo.value;
        if (subList && subList.length > 0) {
          let arr = subList.filter((sub) => sub.key === subKey);
          if (arr.length == 0) {
            console.error('没找到与之匹配的子表', subKey);
            return;
          }
          if (arr[0].relationType == 1) {
            let subInstance = getSubTableInstance(subKey);
            subInstance.executeFillRule();
          } else {
            let subFieldProperties = toRaw(defaultValueFields[subKey]);
            let row = toRaw($event.row);
            loadFormFieldsDefVal(
              subFieldProperties,
              (values) => {
                const { row: row2, target } = $event;
                let v = [{ rowKey: row2.id, values: Object.assign({}, values) }];
                target.setValues(v);
              },
              row
            );
          }
        }
      }
      let context = {
        tableName,
        loading,
        subActiveKey,
        onlineFormRef,
        getFieldsValue,
        setFieldsValue,
        submitFlowFlag,
        subFormHeight,
        subTableHeight,
        refMap,
        triggleChangeValues,
        triggleChangeValue,
        sh: fieldDisplayStatus,
        clearSubRows,
        addSubRows,
        clearThenAddRows,
        changeOptions,
        isUpdate,
        getSubTableInstance,
        updateSchema,
        executeMainFillRule,
        executeSubFillRule,
      };
      resetContext(context);

      return {
        tableName,
        onlineFormRef,
        registerForm,
        loading,
        subActiveKey,
        hasSubTable,
        subTabInfo,
        refMap,
        subFormHeight,
        getSubTableForeignKeyValue,
        isUpdate,
        handleSubFormChange,
        subTableHeight,
        onlineFormDisabled,
        subDataSource,
        getSubTableAuthPre,
        handleAdded,
        handleSubTableDefaultValue,
        handleValueChange,
        openSubFormModalForAdd,
        openSubFormModalForEdit,
        show,
        createRootProperties,
        handleSubmit,
        sh: fieldDisplayStatus,
        handleCgButtonClick,
        handleCustomFormSh,
        handleCustomFormEdit,
        dbData,
        onOpenReportPrint,
        onlineExtConfigJson,
        registerPopModal,
        popTableName,
        getPopFormData,
        popModalRequest,
        onCloseModal,
      };
    },
  });
</script>
<style scoped></style>
